#include "common.h"

int main()
{
    //生成key值
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if (key < 0)
    {
        perror("ftok");
        return 1;
    }

    //创建共享内存
    //这里 | 0666,就是给这个内存段设置权限
    //创建全新的shm,如果和系统存在的ID冲突,我们出错返回
    int shmid = shmget(key, SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid == -1)
    {
        perror("shmget");
        return 2;
    }

    cout << "key : " << key << " shmid : " << shmid << endl;

    sleep(3);
    //进程挂接到共享内存
    //这个地址是虚拟的地址,同时malloc申请的也是虚拟的地址
    //所有我们用户能够直接使用的地址,都是虚拟地址
    char* mem = (char*)shmat(shmid, NULL, 0);
    cout << "server attahes shm success" << endl;

    //这里就是我们进程间通信的逻辑
    //这里我们没有使用pipe or fifo中的read类似的接口
    //read or write的本质:将数据从内核拷贝到进程,or 把进程的数据拷贝到内核
    //共享内存一旦建立好并映射进自己进程的地址空间,该进程就可以直接看到该共享内存
    //就如同malloc的空间一样,不需要任何的系统调用接口,就可以直接使用
    int count = 10;
    while(count--)
    {
        sleep(1);
        //这里我们让server认为共享内存里面放的是一个字符串
        cout << mem << endl;
        //当client端,没有进行数据的写入的时候,server端是可以直接读取shn的,不会等待client端写入
        //共享内存不提供任何同步或者互斥机制,需要程序员自行保证数据的安全
    }

    sleep(3);
    //进程和共享内存去挂接
    shmdt(mem);
    cout << "server detaches shm success" << endl;

    sleep(3);
    //删除共享内存
    //进程退出的时候,创建的共享内存不回主动释放
    //system V的IPC资源,生命周期是随内核的!
    //只能通过程序员显式的释放(命令,system call),或者是OS重启
    shmctl(shmid, IPC_RMID, NULL);
    cout << "key : " << key << " shmid : " << shmid << " ->  shm delete success!" << endl;

    return 0;
}
